package io.github.pnoker.driver.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import io.github.pnoker.common.driver.entity.bean.PointValue;
import io.github.pnoker.common.driver.entity.bean.RValue;
import io.github.pnoker.common.driver.entity.bo.DeviceBO;
import io.github.pnoker.common.driver.entity.bo.PointBO;
import io.github.pnoker.common.driver.entity.dto.PointAttributeConfigDTO;
import io.github.pnoker.common.driver.entity.dto.PointAttributeDTO;
import io.github.pnoker.common.driver.grpc.client.DeviceClient;
import io.github.pnoker.common.driver.grpc.client.PointClient;
import io.github.pnoker.common.driver.metadata.DriverMetadata;
import io.github.pnoker.common.driver.service.DriverSenderService;
import io.github.pnoker.common.exception.ServiceException;
import io.github.pnoker.common.mqtt.entity.MqttMessage;
import io.github.pnoker.driver.service.ResolveMqttMessageService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class ResolveMqttMessageServiceImpl implements ResolveMqttMessageService {




    @Resource
    private DeviceClient deviceClient;

    @Resource
    private PointClient pointClient;

    @Resource
    private DriverMetadata driverMetadata;

    @Resource
    private DriverSenderService driverSenderService;

    Map<String, DeviceBO> deviceBOMap = new HashMap<>();

    Map<Long, PointBO> pointBOMap = new HashMap<>();


    /**
     * 获取设备信息
     */
    public Map<String,DeviceBO > getDeviceBoMap() {

        Map<String,DeviceBO > result = new HashMap<>();
        List<DeviceBO> deviceBOS = deviceClient.list();
        if (!deviceBOS.isEmpty()) {
            result =  deviceBOS.parallelStream().collect(Collectors.toMap(DeviceBO::getDeviceName, s->s,(s, s1)->s));
        }
        return result;
    }

    /**
     *
     * @return
     */
    public Map<Long,PointBO> getPointBoMap() {

        Map<Long,PointBO > result = new HashMap<>();
        List<PointBO> pointBOS = pointClient.list();
        if (!pointBOS.isEmpty()) {
            result =  pointBOS.parallelStream().collect(Collectors.toMap(PointBO::getId, s->s,(s, s1)->s));
        }
        return result;
    }


    /**
     *通过属性名称获取属性id
     * @param attributeName
     * @return
     */
    public Long getPointAttributeId(String attributeName) {

        Map<Long, PointAttributeDTO> attributeMap = driverMetadata.getPointAttributeIdMap();
        Optional<Long> optionalLong = attributeMap.keySet().stream().filter(s -> attributeMap.get(s).getAttributeName().equals(attributeName)).findAny();
        return optionalLong.orElse(null);

    }



    /**
     *解析获取pointValue从mqtt message中
     * @param mqttMessage
     */
    public List<PointValue> getPoinValue(MqttMessage mqttMessage) {

        List<PointValue> allPointValues = new ArrayList<>();

        //获取device
        JSONObject jsonObject = JSONObject.parseObject(mqttMessage.getPayload());
        DeviceBO deviceBO = getDeviceBoMap().get(jsonObject.getString("name"));

        //获取point
        Optional<Long> optionalLong = deviceBO.getPointIds().parallelStream().filter(s -> this.pointBOMap.get(s) == null).findAny();
        if (optionalLong.isPresent()) {
            this.pointBOMap = getPointBoMap();
        }
        //get DeviceName by income Msg
        String inputValues = "inputValue";
        String outputValues = "outputValue";
        String channelDiag = "channel";

        Set<String> keySets = jsonObject.keySet();
        if(!keySets.isEmpty()) {
            for (String item : keySets) {
                String strValue = jsonObject.getString(item);
                boolean TargetBit = false;

                if (item.equals(channelDiag)) {
                    strValue = analyticString(jsonObject.getString(item), 8);
                    TargetBit = true;
                } else if (item.equals(inputValues)) {
                    strValue = analyticString(jsonObject.getString(item), 16);
                    TargetBit = true;
                } else if (item.equals(outputValues)) {
                    strValue = analyticString(jsonObject.getString(item), 16);
                    TargetBit = true;
                } else if (item.equals("name")) {
                    continue;
                }
                try {
                    List<PointValue> pointValues = setValue(pointBOMap, deviceBO, item, strValue, TargetBit);
                    allPointValues.addAll(pointValues);
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
            }
        }
        if (!allPointValues.isEmpty()) {
            driverSenderService.pointValueSender(allPointValues);
        }
        return null;

    }


    /**
     * 字符串解析
     * @param value
     * @param binaryLength
     * @return
     */
    public String analyticString(String value,int binaryLength){
        StringBuilder combinedBinary = new StringBuilder();
        if (!value.isEmpty()) {
            String[] singleInputValue = value.split("=");
            for (String part : singleInputValue) {
                if (!part.isEmpty()) { // 检查部分是否为空
                    int num = Integer.parseInt(part);
                    String binary = String.format("%" + binaryLength + "s", Integer.toBinaryString(num)).replace(' ', '0'); // 转换为 8 位二进制字符串
                    String reversedBinary = new StringBuilder(binary).reverse().toString(); // 倒序排列二进制字符串
                    combinedBinary.append(reversedBinary); // 将倒序排列的二进制字符串添加到合并的字符串中
                }
            }
            return combinedBinary.toString();
        }
        return null;
    }


    public List<PointValue>  setValue(Map<Long,PointBO > pointBOMap, DeviceBO deviceBO, String key,String value,boolean TargetBit){
        List<PointValue> pointValues = new ArrayList<>();

        PointAttributeConfigDTO pointAttributeConfigDTO = getPointAttributeConfig(deviceBO,"flag",key);
        if (!pointBOMap.containsKey(pointAttributeConfigDTO.getPointId())) {
            throw new ServiceException("未找到point");
        }
        String localValue = value;
        if (TargetBit) {
            Long targetBitPointAttributeId = getPointAttributeId("TargetBit");
            String strTargetBit = deviceBO.getPointAttributeConfigIdMap().get(pointAttributeConfigDTO.getPointId()).get(targetBitPointAttributeId).getConfigValue();
            int intTargetBit = Integer.parseInt(strTargetBit);
            boolean signalBitValue = value.charAt(intTargetBit - 1) == '1';//如果是1则为true，否则为false
            localValue = String.valueOf(signalBitValue);
        }
        RValue rValue = new RValue();
        rValue.setValue(localValue);
        rValue.setDevice(deviceBO);
        rValue.setPoint(pointBOMap.get(pointAttributeConfigDTO.getPointId()));
        PointValue pointValue = new PointValue(rValue);
        if (ObjectUtil.isNotNull(pointValue)) {
            pointValues.add(pointValue);
        }
        return pointValues;

    }




    /**
     * 获取属性配置信息
     * @param deviceBO
     * @param attributeName
     * @param key
     * @return
     */
    public PointAttributeConfigDTO getPointAttributeConfig(DeviceBO deviceBO,String attributeName,String key) {

        Long attributeId = getPointAttributeId(attributeName);
        Optional<PointAttributeConfigDTO> first =  deviceBO.getPointIds().stream().map(s -> {
            Map<Long, PointAttributeConfigDTO> dtoMap = deviceBO.getPointAttributeConfigIdMap().get(s);
            if (dtoMap!=null && dtoMap.get(attributeId).getConfigValue().equals(key)) {
                return dtoMap.get(attributeId);
            } else {
                return null;
            }
        }).filter(Objects::nonNull).findAny();
        if(first.isPresent()){
            return first.get();
        }else {
            throw new ServiceException("未找到point attribute config key: " + key);
        }
    }

}
